﻿<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>fluid</title>
    <meta charset="utf-8" />
    <link href="../../../ThirdParty/Cesium/Widgets/widgets.css" rel="stylesheet" />
    <style>
        html, body, #cesiumContainer {
            width: calc(100%);
            height: calc(100%);
            margin:0;padding:0;
        }
    </style>
</head>
<body>
    <script id="2d-vertex-shader" type="x-shader/x-vertex">

        attribute vec2 a_position;

        void main() {
           gl_Position = vec4(a_position, 0, 1);
        }
    </script>

    <script id="resetVelocityShader" type="x-shader/x-fragment">
        precision mediump float;

        void main() {
            gl_FragColor = vec4(1.0, 0.0, 0.0, 0.0);
        }
    </script>

    <script id="boundaryConditionsShader" type="x-shader/x-fragment">
        precision mediump float;

        uniform sampler2D u_texture;
        uniform float u_scale;
        uniform vec2 u_textureSize;

        uniform vec2 u_obstaclePosition;//scaled to texture size
        uniform float u_obstacleRad;

        void main() {
            vec2 fragCoord = gl_FragCoord.xy;

            vec2 dir = fragCoord - 3.0*vec2(0.5, 0.5) - u_obstaclePosition;//not sure where this fac of 3 came from?
            float dist = length(dir);
            if (dist < u_obstacleRad){
                gl_FragColor = vec4(0);
                return;
            }

            if (dist < u_obstacleRad+1.0){
                gl_FragColor = u_scale*texture2D(u_texture, (fragCoord + dir/dist*2.0)/u_textureSize);
                return;
            }

            gl_FragColor = texture2D(u_texture, fragCoord/u_textureSize);
        }
    </script>

    <script id="2d-render-shader" type="x-shader/x-fragment">
        precision mediump float;

        uniform sampler2D u_material;
        uniform vec2 u_obstaclePosition;
        uniform vec2 u_textureSize;
        uniform float u_obstacleRad;

        void main() {
            vec2 fragCoord = gl_FragCoord.xy;

            vec2 dir = fragCoord - vec2(0.5, 0.5) - u_obstaclePosition;
            float dist = length(dir);
            if (dist < u_obstacleRad){
                gl_FragColor = vec4(0.925, 0, 0.55, 1);
                return;
            }

            float mat1 = texture2D(u_material, fragCoord/u_textureSize).x;
            vec3 color = vec3(0.98, 0.93, 0.84);
            gl_FragColor = vec4(mat1*color, 1);
        }
    </script>

    <script id="gradientSubtractionShader" type="x-shader/x-fragment">
        precision mediump float;

        uniform sampler2D u_velocity;
        uniform sampler2D u_pressure;

        uniform vec2 u_textureSize;

        uniform float u_const;

        vec2 repeatBoundary(vec2 coord){
            coord -= vec2(0.5, 0.5);
            //if (coord.x < 0.0) coord.x = u_textureSize.x-1.0;
            if (coord.x >= u_textureSize.x-1.0) coord.x = 0.0;
            if (coord.y < 0.0) coord.y = u_textureSize.y-1.0;
            else if (coord.y >= u_textureSize.y-1.0) coord.y = 0.0;
            coord += vec2(0.5, 0.5);
            return coord;
        }

        void main() {

            vec2 fragCoord = gl_FragCoord.xy;

            vec2 currentVelocity = texture2D(u_velocity, fragCoord/u_textureSize).xy;

            float n = texture2D(u_pressure, repeatBoundary(fragCoord+vec2(0.0, 1.0))/u_textureSize).x;
            float s = texture2D(u_pressure, repeatBoundary(fragCoord+vec2(0.0, -1.0))/u_textureSize).x;
            float e = texture2D(u_pressure, (fragCoord+vec2(1.0, 0.0))/u_textureSize).x;
            float w = texture2D(u_pressure, (fragCoord+vec2(-1.0, 0.0))/u_textureSize).x;

            gl_FragColor = vec4(currentVelocity-u_const*vec2(e-w, n-s), 0, 0);
        }
    </script>

    <script id="divergenceShader" type="x-shader/x-fragment">
        precision mediump float;

        uniform sampler2D u_velocity;

        uniform vec2 u_textureSize;

        uniform float u_const;

        vec2 repeatBoundary(vec2 coord){
            coord -= vec2(0.5, 0.5);
            if (coord.x < 0.0) coord.x = u_textureSize.x-1.0;
            else if (coord.x >= u_textureSize.x-1.0) coord.x = 0.0;
            if (coord.y < 0.0) coord.y = u_textureSize.y-1.0;
            else if (coord.y >= u_textureSize.y-1.0) coord.y = 0.0;
            coord += vec2(0.5, 0.5);
            return coord;
        }

        void main() {

            vec2 fragCoord = gl_FragCoord.xy;

            //finite difference formulation of divergence

            //periodic boundary

            float n = texture2D(u_velocity, repeatBoundary(fragCoord+vec2(0.0, 1.0))/u_textureSize).y;
            float s = texture2D(u_velocity, repeatBoundary(fragCoord+vec2(0.0, -1.0))/u_textureSize).y;

            float e = texture2D(u_velocity, repeatBoundary(fragCoord+vec2(1.0, 0.0))/u_textureSize).x;
            float w = texture2D(u_velocity, (fragCoord+vec2(-1.0, 0.0))/u_textureSize).x;

            float div = u_const*(e-w + n-s);
            gl_FragColor = vec4(div, 0, 0, 0);
        }
    </script>

    <script id="forceShader" type="x-shader/x-fragment">
        precision mediump float;

        uniform sampler2D u_velocity;

        uniform vec2 u_textureSize;

        uniform vec2 u_mouseCoord;
        uniform vec2 u_mouseDir;

        uniform float u_reciprocalRadius;

        uniform float u_dt;

        void main() {

            vec2 fragCoord = gl_FragCoord.xy;

            vec2 currentVelocity = texture2D(u_velocity, fragCoord/u_textureSize).xy;

            vec2 pxDist = fragCoord - u_mouseCoord;
            currentVelocity += u_mouseDir*u_dt*exp(-(pxDist.x*pxDist.x+pxDist.y*pxDist.y)*u_reciprocalRadius);

            gl_FragColor = vec4(currentVelocity, 0, 0);
        }
    </script>

    <script id="jacobiShader" type="x-shader/x-fragment">
        precision mediump float;

        uniform sampler2D u_b;
        uniform sampler2D u_x;

        uniform vec2 u_textureSize;

        uniform float u_alpha;
        uniform float u_reciprocalBeta;

        void main() {

            vec2 fragCoord = gl_FragCoord.xy;

            vec2 currentState = texture2D(u_b, fragCoord/u_textureSize).xy;

            //implicitly solve diffusion via jacobi iteration

            vec2 n = texture2D(u_x, (fragCoord+vec2(0.0, 1.0))/u_textureSize).xy;
            vec2 s = texture2D(u_x, (fragCoord+vec2(0.0, -1.0))/u_textureSize).xy;
            vec2 e = texture2D(u_x, (fragCoord+vec2(1.0, 0.0))/u_textureSize).xy;
            vec2 w = texture2D(u_x, (fragCoord+vec2(-1.0, 0.0))/u_textureSize).xy;

            vec2 nextState = (n + s + e + w + u_alpha * currentState) * u_reciprocalBeta;

            gl_FragColor = vec4(nextState, 0, 0);
        }
   </script>

    <script id="advectShaderMat" type="x-shader/x-fragment">
        precision mediump float;

        uniform sampler2D u_velocity;
        uniform sampler2D u_material;

        uniform vec2 u_textureSize;
        uniform float u_scale;

        uniform float u_dt;

        vec2 bilinearInterp(vec2 pos, sampler2D texture, vec2 size){
            //bilinear interp between nearest cells

            vec2 pxCenter = vec2(0.5, 0.5);

            vec2 ceiled = ceil(pos);
            vec2 floored = floor(pos);

            vec2 n = texture2D(texture, (ceiled+pxCenter)/size).xy;//actually ne
            vec2 s = texture2D(texture, (floored+pxCenter)/size).xy;//actually sw
            if (ceiled.x != floored.x){
                vec2 se = texture2D(texture, (vec2(ceiled.x, floored.y)+pxCenter)/size).xy;
                vec2 nw = texture2D(texture, (vec2(floored.x, ceiled.y)+pxCenter)/size).xy;
                n = n*(pos.x-floored.x) + nw*(ceiled.x-pos.x);
                s = se*(pos.x-floored.x) + s*(ceiled.x-pos.x);
            }
            vec2 materialVal = n;
            if (ceiled.y != floored.y){
                materialVal = n*(pos.y-floored.y) + s*(ceiled.y-pos.y);
            }
            return materialVal;
        }

        void main() {

            vec2 fragCoord = gl_FragCoord.xy;

            vec2 pxCenter = vec2(0.5, 0.5);

            //bilinear interp
            //vec2 currentVelocity = 1.0/u_scale*texture2D(u_velocity, fragCoord/u_textureSize).xy;
            vec2 currentVelocity = 1.0/u_scale*bilinearInterp((fragCoord-pxCenter)*u_scale + pxCenter, u_velocity, u_textureSize*u_scale);

            //implicitly solve advection

            if (fragCoord.x < 1.0){//boundary
                float numCols = floor(u_textureSize.y/10.0);
                if (mod(numCols, 2.0) == 1.0) numCols--;
                float numPx = u_textureSize.y/numCols;
                if (floor(mod((fragCoord.y-2.0)/numPx, 2.0)) == 0.0) gl_FragColor = vec4(1, 0, 0, 0);
                else gl_FragColor = vec4(0, 0, 0, 0);
                return;
            }
            if (length(currentVelocity) == 0.0) {//no velocity
                gl_FragColor = vec4(texture2D(u_material, fragCoord/u_textureSize).xy, 0, 0);
                return;
            }

            vec2 pos = fragCoord - pxCenter - u_dt*currentVelocity;

            if (pos.x >= u_textureSize.x-1.0) {
                gl_FragColor = vec4(0, 0, 0, 0);
                return;
            }

            //periodic boundary in y
            if (pos.y < 0.0) pos.y += u_textureSize.y-1.0;
            if (pos.y >= u_textureSize.y-1.0) pos.y -= u_textureSize.y-1.0;

            gl_FragColor = vec4(bilinearInterp(pos, u_material, u_textureSize), 0, 0);
        }
    </script>

    <script id="advectShaderVel" type="x-shader/x-fragment">
        precision mediump float;

        uniform sampler2D u_velocity;
        uniform sampler2D u_material;

        uniform vec2 u_textureSize;
        uniform float u_scale;

        uniform float u_dt;

        void main() {

            vec2 fragCoord = gl_FragCoord.xy;

            vec2 currentVelocity = u_scale*texture2D(u_velocity, fragCoord/u_textureSize).xy;

            //implicitly solve advection

            if (length(currentVelocity) == 0.0) {//boundary or no velocity
                gl_FragColor = vec4(texture2D(u_material, fragCoord/u_textureSize).xy, 0, 0);
                return;
            }

            vec2 pxCenter = vec2(0.5, 0.5);
            vec2 pos = fragCoord - pxCenter - u_dt*currentVelocity;

             if (pos.x < 1.0) {
               gl_FragColor = vec4(1.0, 0, 0, 0);
               return;
            }
            if (pos.x >= u_textureSize.x-1.0) {
                gl_FragColor = vec4(0, 0, 0, 0);
                //return;
            }
            if (pos.x >= u_textureSize.x-1.0) pos.x -= u_textureSize.x-1.0;

            //periodic boundary in y
            if (pos.y < 0.0) {
                pos.y += u_textureSize.y-1.0;
            }
            if (pos.y >= u_textureSize.y-1.0) {
                pos.y -= u_textureSize.y-1.0;
            }

            //bilinear interp between nearest cells
            vec2 ceiled = ceil(pos);
            vec2 floored = floor(pos);

            vec2 n = texture2D(u_material, (ceiled+pxCenter)/u_textureSize).xy;//actually ne
            vec2 s = texture2D(u_material, (floored+pxCenter)/u_textureSize).xy;//actually sw
            if (ceiled.x != floored.x){
                vec2 se = texture2D(u_material, (vec2(ceiled.x, floored.y)+pxCenter)/u_textureSize).xy;
                vec2 nw = texture2D(u_material, (vec2(floored.x, ceiled.y)+pxCenter)/u_textureSize).xy;
                n = n*(pos.x-floored.x) + nw*(ceiled.x-pos.x);
                s = se*(pos.x-floored.x) + s*(ceiled.x-pos.x);
            }
            vec2 materialVal = n;
            if (ceiled.y != floored.y){
                materialVal = n*(pos.y-floored.y) + s*(ceiled.y-pos.y);
            }

            gl_FragColor = vec4(materialVal, 0, 0);
        }
    </script>
    <div id="cesiumContainer">
    </div>
    <div id="creditContainer" style="display: none;">
    </div>
    <script src="../../../ThirdParty/Cesium/Cesium.js" type="text/javascript"></script>
    <!--<script src="./GlBoilerplate.js"></script>
    <script src="./GPUMath.js"></script>
    <script src="main.js"></script>-->

    <script src="../../../appconfig.js"></script>
    <script src="../../../dist/CesiumMeshVisualizer.min.js"></script>
    <script src="../common.js"></script>
    <script src="index.js"></script>
    <!--使用requirejs模块管理库进行加载-->
    <!--<script src="../../../ThirdParty/require.js"type="text/javascript" data-main="./index"></script>-->

</body>
</html>
